<script setup lang="ts">
import groupBy from 'lodash.groupby'
import { ElLoading } from 'element-plus'

import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
import { simpleLangName } from '../../../config/scripts/languages'
import useExtensionsRepositoryQuery from '../../queries/useExtensionsRepositoryQuery'
import type { Extension } from '../../queries/useExtensionsRepositoryQuery'
import ExtensionList from './ExtensionList.vue'
import type { Sort } from './ExtensionFilters.vue'

const { data: extensions, isLoading } = useExtensionsRepositoryQuery({
  select: (response) => {
    const values: Extension[][] = Object.values(groupBy(response, 'lang'))
    values.sort(languageComparator)

    return values
  },
})

const filters = reactive({
  search: '',
  lang: [] as string[],
  sort: 'Ascending' as Sort,
})

function languageComparator(a: Extension[], b: Extension[]) {
  const langA = simpleLangName(a[0].lang)
  const langB = simpleLangName(b[0].lang)
  if (langA === 'All' && langB === 'English')
    return -1

  if (langA === 'English' && langB === 'All')
    return 1

  if (langA === 'English')
    return -1

  if (langB === 'English')
    return 1

  if (langA < langB)
    return -1

  if (langA > langB)
    return 1

  return 0
}

const filteredExtensions = computed(() => {
  const filtered: Extension[][] = []

  for (const group of (extensions.value ?? [])) {
    let filteredGroup = filters.lang.length
      ? (filters.lang.includes(group[0].lang) ? group : [])
      : group

    if (filters.search) {
      filteredGroup = filteredGroup.filter(
        ext =>
          ext.name.toLowerCase().includes(filters.search.toLowerCase())
          || ext.sources.some(source => source.id.includes(filters.search)),
      )
    }

    if (filters.sort && filters.sort === 'Descending')
      filteredGroup = filteredGroup.reverse()

    if (filteredGroup.length)
      filtered.push(filteredGroup)
  }

  return filtered
})

const loadingInstance = ref<ReturnType<typeof ElLoading['service']>>()

onMounted(() => {
  loadingInstance.value = ElLoading.service({
    target: '.extensions',
    fullscreen: false,
    background: 'transparent',
  })
})

watch(extensions, async () => {
  if (window.location.hash) {
    await nextTick()
    const extElement = document.getElementById(window.location.hash.substring(1))

    extElement?.scrollIntoView({ behavior: 'smooth' })
    extElement?.focus({ preventScroll: true })
  }
})

watch([isLoading, loadingInstance], async ([newIsLoading]) => {
  if (!newIsLoading)
    loadingInstance.value?.close()
})
</script>

<template>
  <ExtensionFilters
    v-model:search="filters.search"
    v-model:lang="filters.lang"
    v-model:sort="filters.sort"
    :extensions="extensions ?? []"
  />
  <div class="extensions">
    <ExtensionList v-if="!isLoading" :extensions="filteredExtensions" />
  </div>
</template>

<style lang="stylus" scoped>
.extensions {
  min-height: 200px
}
</style>
